package org.shoukaiseki.aliyun.captchasms.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import org.shoukaiseki.aliyun.captchasms.config.CaptchaPhonenumberConfiguration;
import org.shoukaiseki.aliyun.captchasms.constant.CaptchaSmsConstants;
import org.shoukaiseki.aliyun.captchasms.exception.CaptchaPhonenumberException;
import org.shoukaiseki.aliyun.captchasms.logger.CaptchaPhonenumberLoggers;
import org.shoukaiseki.aliyun.captchasms.service.ICaptchaSmsValidateService;
import org.shoukaiseki.aliyun.sms.config.AliyunSmsConfigProperties;
import org.shoukaiseki.common.logger.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.NumberUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Random;


@Service
public class CaptchaSmsValidateServiceImpl implements ICaptchaSmsValidateService {

    public static final Logger logger= CaptchaPhonenumberLoggers.CAPTCHA_PHONENUMBER_LOGGER;


    @Resource(name = CaptchaPhonenumberConfiguration.CAPTCHA_ALIYUN_ACS_CLIENT_BEAN_NAME)
    IAcsClient acsClient;

    @Resource(name=CaptchaPhonenumberConfiguration.CAPTCHA_ALIYUN_SMS_PROP_BEAN_NAME)
    AliyunSmsConfigProperties aliyunSmsConfigProperties;

    @Value("${sks.aliyun.sms.captcha.debug:false}")
    private boolean debug=false;

    @Override
    public void sendCaptcha(String phonenumber) {
        sendCaptcha(phonenumber,100000, 999999);
    }

    @Override
    public void sendCaptcha(String phonenumber, int minCode, int maxCode) {
        int random = getRandom(minCode,maxCode);
        //获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        //从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        HttpSession session = request.getSession();

        //存放验证码
        session.setAttribute(CaptchaSmsConstants.CAPTCHA_SMS_SESSION_ATTRNAME_PHONENUMBER,phonenumber);
        session.setAttribute(CaptchaSmsConstants.CAPTCHA_SMS_SESSION_ATTRNAME_CODE,random);
        session.setAttribute(CaptchaSmsConstants.CAPTCHA_SMS_SESSION_ATTRNAME_CODETIME,System.currentTimeMillis());

        if(!debug){
            sendCaptchaSms(random,phonenumber);
        }
    }


    public void sendCaptchaSms(int code,String phonenumber){
        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain(aliyunSmsConfigProperties.getSysDomain());
        request.setSysVersion(aliyunSmsConfigProperties.getSysVersion());
        request.setSysAction(aliyunSmsConfigProperties.getSysAction());
        request.putQueryParameter("RegionId", aliyunSmsConfigProperties.getRegionId());
        request.putQueryParameter("SignName", aliyunSmsConfigProperties.getSignName());
        request.putQueryParameter("TemplateCode", aliyunSmsConfigProperties.getTemplateCode());
        request.putQueryParameter("PhoneNumbers", phonenumber);
        request.putQueryParameter("TemplateParam", "{\"code\":\""+code+"\"}");
        try {
            logger.info("code={}",code);
            logger.info("phonenumber={}",phonenumber);
            CommonResponse response = acsClient.getCommonResponse(request);
            String data = response.getData();
            JSONObject jsonObject = JSONObject.parseObject(data);
            Object code1 = jsonObject.get("Code");
            logger.info("result={}",data);
            if ("OK".equals(code1)) {
            }else{
                logger.error("阿里云短信发送失败={},手机号={},验证码={}",jsonObject.get("Message"),phonenumber,code);
                throw new CaptchaPhonenumberException("短信发送出错");
            }
            logger.info(data);
        } catch (ServerException e) {
            logger.error("",e);
            throw new CaptchaPhonenumberException("短信发送出错");
        } catch (ClientException e) {
            logger.error("",e);
            throw new CaptchaPhonenumberException("短信发送出错");
        }
    }

    @Override
    public void validate() {
        //获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        //从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        Object phonenumObj=request.getParameter(CaptchaSmsConstants.CAPTCHA_SMS_PARAM_PHONENUMBER);
        String phonenum= StringUtils.isEmpty(phonenumObj)?null:phonenumObj.toString();
        Object validateCodeObj=request.getParameter(CaptchaSmsConstants.CAPTCHA_SMS_PARAM_CODE);
        Integer validateCode=StringUtils.isEmpty(validateCodeObj)?null:NumberUtils.parseNumber(validateCodeObj.toString(),Integer.class);
        validate(request,validateCode,phonenum);
    }

    @Override
    public void validate(HttpServletRequest request,Integer validateCode,String phonenum) {
        HttpSession session = request.getSession();
        Object codeObj = session.getAttribute(CaptchaSmsConstants.CAPTCHA_SMS_SESSION_ATTRNAME_CODE);
        Object codetimeObj = session.getAttribute(CaptchaSmsConstants.CAPTCHA_SMS_SESSION_ATTRNAME_CODETIME);
        Object phonenumberObj = session.getAttribute(CaptchaSmsConstants.CAPTCHA_SMS_SESSION_ATTRNAME_PHONENUMBER);

        if(StringUtils.isEmpty(codeObj)||StringUtils.isEmpty(codetimeObj)||StringUtils.isEmpty(phonenumberObj)){
           throw new CaptchaPhonenumberException("验证码有效期超过5分钟，请重新发送");
        }
        Integer code = NumberUtils.parseNumber(codeObj.toString(), Integer.class);
        Long codetime = NumberUtils.parseNumber(codetimeObj.toString(), Long.class);


        if (!phonenum.equals(phonenumberObj.toString())) {
            throw new CaptchaPhonenumberException("手机号码不一致，劝你不要动坏心思");
        }
        long l = System.currentTimeMillis();

        if(l-1000*60*5>codetime){
            throw new CaptchaPhonenumberException("验证码有效期超过5分钟，请重新发送");
        }
        if(!validateCode.equals(code)){
            logger.info("系统存放code=[{}],validateCode=[{}]",code,validateCode);
            throw new CaptchaPhonenumberException("验证码不一致");
        }

        // 验证码清除，防止多次使用。
        session.removeAttribute(CaptchaSmsConstants.CAPTCHA_SMS_SESSION_ATTRNAME_CODE);
        session.removeAttribute(CaptchaSmsConstants.CAPTCHA_SMS_SESSION_ATTRNAME_CODETIME);
        session.removeAttribute(CaptchaSmsConstants.CAPTCHA_SMS_SESSION_ATTRNAME_PHONENUMBER);



    }


    public static int getRandom(int min, int max)
    {
        Random random = new Random();
        int i = random.nextInt(max) % (max - min + 1) + min;
        return i;

    }

}
